package com.media.system.service.impl;

import com.media.system.common.core.domain.AjaxResult;
import com.media.system.common.utils.JwtUtils;
import com.media.system.domain.User;
import com.media.system.domain.model.LoginUser;
import com.media.system.mapper.UserMapper;
import com.media.system.security.service.TokenService;
import com.media.system.service.LoginService;
import com.media.system.service.dto.LoginRequest;
import com.media.system.service.dto.RegisterRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 登录服务实现
 * 
 * @author Claude
 * @since 2024-01-20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    private final AuthenticationManager authenticationManager;
    private final TokenService tokenService;
    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtils jwtUtils;

    @Override
    public AjaxResult login(LoginRequest loginRequest) {
        try {
            
            // 验证用户凭证
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
            );

            // 获取认证用户信息
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            User user = loginUser.getUser();

            // 更新最后登录信息
            user.setLoginDate(LocalDateTime.now());
            userMapper.updateById(user);

            // 生成令牌
            String token = tokenService.createToken(loginUser);

            // 返回登录成功信息
            return AjaxResult.success()
                .put("token", token)
                .put("user", user);

        } catch (BadCredentialsException e) {
            log.warn("用户 {} 登录失败：密码错误", loginRequest.getUsername());
            return AjaxResult.error("用户名或密码错误");
        } catch (Exception e) {
            log.error("用户 {} 登录异常", loginRequest.getUsername(), e);
            return AjaxResult.error("登录失败，请稍后重试");
        }
    }

    @Override
    @Transactional
    public AjaxResult register(RegisterRequest registerRequest) {
        try {
            // 检查用户名是否已存在
            if (userMapper.selectByUsername(registerRequest.getUsername()) != null) {
                return AjaxResult.error("用户名已存在");
            }

            // 检查邮箱是否已存在
            if (userMapper.selectByEmail(registerRequest.getEmail()) != null) {
                return AjaxResult.error("邮箱已被注册");
            }

            // 创建新用户
            User user = new User();
            user.setUsername(registerRequest.getUsername());
            user.setEmail(registerRequest.getEmail());
            user.setNickname(registerRequest.getNickname());
            user.setPasswordHash(passwordEncoder.encode(registerRequest.getPassword()));
            user.setStatus(1); // 正常状态

            // 保存用户
            userMapper.insert(user);

            log.info("用户 {} 注册成功", user.getUsername());
            return AjaxResult.success("注册成功");

        } catch (Exception e) {
            log.error("用户注册异常", e);
            return AjaxResult.error("注册失败，请稍后重试");
        }
    }

    @Override
    public AjaxResult logout() {
        try {
            // 获取当前登录用户
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() instanceof LoginUser) {
                LoginUser loginUser = (LoginUser) authentication.getPrincipal();
                
                // 删除用户缓存
                tokenService.delLoginUser(loginUser.getToken());
                
                log.info("用户 {} 注销成功", loginUser.getUsername());
            }
            
            return AjaxResult.success("注销成功");
        } catch (Exception e) {
            log.error("用户注销异常", e);
            return AjaxResult.error("注销失败");
        }
    }

    @Override
    public AjaxResult refreshToken(String refreshToken) {
        try {
            // 验证刷新令牌
            if (!jwtUtils.validateToken(refreshToken)) {
                return AjaxResult.error("无效的刷新令牌");
            }

            // 从令牌中获取用户名
            String username = jwtUtils.getUsernameFromToken(refreshToken);
            
            // 获取用户信息
            User user = userMapper.selectByUsername(username);
            if (user == null || user.getStatus() != 1) {
                return AjaxResult.error("用户不存在或已被禁用");
            }

            // 创建新的登录用户对象
            LoginUser loginUser = new LoginUser();
            loginUser.setUser(user);
            loginUser.setUserId(user.getUserId());

            // 生成新的访问令牌
            String newToken = tokenService.createToken(loginUser);

            return AjaxResult.success()
                .put("token", newToken)
                .put("user", user);

        } catch (Exception e) {
            log.error("刷新令牌异常", e);
            return AjaxResult.error("刷新令牌失败");
        }
    }

    @Override
    public AjaxResult getCurrentUserInfo() {
        try {
            // 获取当前登录用户
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || !(authentication.getPrincipal() instanceof LoginUser)) {
                return AjaxResult.error("用户未登录");
            }

            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            User user = loginUser.getUser();
            
            if (user == null) {
                return AjaxResult.error("用户信息不存在");
            }

            // 返回用户信息（不包含密码等敏感信息）
            user.setPasswordHash(null);
            
            return AjaxResult.success("获取用户信息成功", user);

        } catch (Exception e) {
            log.error("获取用户信息异常", e);
            return AjaxResult.error("获取用户信息失败");
        }
    }
}